import 'package:flutter_bloc/flutter_bloc.dart';
import '../entity/content_submission.dart';
import '../entity/user.dart';
import '../data/content_repository.dart';
import '../utils/media_processor.dart';
import '../utils/whisper.dart';

class ContentCuratorState {
  final bool isProcessing;
  final List<ContentSubmission> submissions;
  final List<ChallengeTask> availableTasks;
  final String? errorMessage;
  final bool hasMoreContent;

  const ContentCuratorState({
    this.isProcessing = false,
    this.submissions = const [],
    this.availableTasks = const [],
    this.errorMessage,
    this.hasMoreContent = true,
  });

  ContentCuratorState copyWith({
    bool? isProcessing,
    List<ContentSubmission>? submissions,
    List<ChallengeTask>? availableTasks,
    String? errorMessage,
    bool? hasMoreContent,
    bool clearError = false,
  }) {
    return ContentCuratorState(
      isProcessing: isProcessing ?? this.isProcessing,
      submissions: submissions ?? this.submissions,
      availableTasks: availableTasks ?? this.availableTasks,
      errorMessage: clearError ? null : (errorMessage ?? this.errorMessage),
      hasMoreContent: hasMoreContent ?? this.hasMoreContent,
    );
  }
}

class ContentCuratorCubit extends Cubit<ContentCuratorState> {
  final ContentRepository _repository = ContentRepository();
  final MediaProcessor _mediaProcessor = MediaProcessor();

  ContentCuratorCubit() : super(const ContentCuratorState()) {
    _initializeData();
  }

  Future<void> _initializeData() async {
    try {
      emit(state.copyWith(isProcessing: true, clearError: true));

      await _repository.initializeChallengeTasks();
      final tasks = await _repository.getAllChallengeTasks();
      final submissions = await _repository.getAllSubmissions();

      emit(
        state.copyWith(
          isProcessing: false,
          availableTasks: tasks,
          submissions: submissions,
        ),
      );
    } catch (e) {
      emit(
        state.copyWith(
          isProcessing: false,
          errorMessage: 'Failed to initialize data: $e',
        ),
      );
    }
  }

  Future<void> refreshContent() async {
    try {
      emit(state.copyWith(isProcessing: true, clearError: true));

      final submissions = await _repository.getAllSubmissions();

      emit(state.copyWith(isProcessing: false, submissions: submissions));
    } catch (e) {
      emit(
        state.copyWith(
          isProcessing: false,
          errorMessage: 'Failed to refresh content: $e',
        ),
      );
    }
  }

  Future<bool> publishImageSubmission({
    required User author,
    required SubmissionCategory category,
    required String description,
    required List<String> imagePaths,
    String? challengeTaskId,
  }) async {
    try {
      emit(state.copyWith(isProcessing: true, clearError: true));

      if (imagePaths.isEmpty || imagePaths.length > 3) {
        throw Exception('Please select 1-3 images');
      }

      final mediaAssets = await _mediaProcessor.processImageCollection(
        imagePaths,
      );

      if (mediaAssets.isEmpty) {
        throw Exception('Failed to process images');
      }

      ChallengeTask? associatedTask;
      if (category == SubmissionCategory.challengeShare &&
          challengeTaskId != null) {
        associatedTask = await _repository.getChallengeTaskById(
          challengeTaskId,
        );
      }

      final submission = ContentSubmission(
        submissionId: 'sub_${DateTime.now().millisecondsSinceEpoch}',
        authorId: author.id,
        authorName: author.name,
        authorAvatar: author.avatar,
        category: category,
        textDescription: description,
        mediaAssets: mediaAssets,
        associatedTask: associatedTask,
        appreciations: [],
        appreciationCount: 0,
        publishedAt: DateTime.now(),
        lastModified: DateTime.now(),
      );

      final success = await _repository.publishSubmission(submission);

      if (success) {
        final updatedSubmissions = [submission, ...state.submissions];
        emit(
          state.copyWith(isProcessing: false, submissions: updatedSubmissions),
        );

        Whisper.murmur('Content published successfully!');
        return true;
      } else {
        throw Exception('Failed to save submission');
      }
    } catch (e) {
      emit(state.copyWith(isProcessing: false, errorMessage: e.toString()));
      Whisper.hiss('Failed to publish content: $e');
      return false;
    }
  }

  Future<bool> publishVideoSubmission({
    required User author,
    required SubmissionCategory category,
    required String description,
    required String videoPath,
    String? thumbnailPath,
    String? challengeTaskId,
  }) async {
    try {
      emit(state.copyWith(isProcessing: true, clearError: true));

      MediaAsset mediaAsset;
      if (thumbnailPath != null) {
        mediaAsset = MediaAsset(
          assetId: 'vid_${DateTime.now().millisecondsSinceEpoch}',
          localPath: videoPath,
          mediaType: ContentMediaType.videoClip,
          thumbnailPath: thumbnailPath,
          uploadedAt: DateTime.now(),
        );
      } else {
        mediaAsset = await _mediaProcessor.processVideoClip(videoPath);
      }

      ChallengeTask? associatedTask;
      if (category == SubmissionCategory.challengeShare &&
          challengeTaskId != null) {
        associatedTask = await _repository.getChallengeTaskById(
          challengeTaskId,
        );
      }

      final submission = ContentSubmission(
        submissionId: 'sub_${DateTime.now().millisecondsSinceEpoch}',
        authorId: author.id,
        authorName: author.name,
        authorAvatar: author.avatar,
        category: category,
        textDescription: description,
        mediaAssets: [mediaAsset],
        associatedTask: associatedTask,
        appreciations: [],
        appreciationCount: 0,
        publishedAt: DateTime.now(),
        lastModified: DateTime.now(),
      );

      final success = await _repository.publishSubmission(submission);

      if (success) {
        final updatedSubmissions = [submission, ...state.submissions];
        emit(
          state.copyWith(isProcessing: false, submissions: updatedSubmissions),
        );

        Whisper.murmur('Video content published successfully!');
        return true;
      } else {
        throw Exception('Failed to save video submission');
      }
    } catch (e) {
      emit(state.copyWith(isProcessing: false, errorMessage: e.toString()));
      Whisper.hiss('Failed to publish video: $e');
      return false;
    }
  }

  Future<void> toggleAppreciationStatus(
    String submissionId,
    User currentUser,
  ) async {
    try {
      final success = await _repository.toggleAppreciation(
        submissionId,
        currentUser,
      );

      if (success) {
        final updatedSubmissions =
            state.submissions.map((submission) {
              if (submission.submissionId == submissionId) {
                final isCurrentlyAppreciated = submission.isAppreciatedByUser(
                  currentUser.id,
                );

                if (isCurrentlyAppreciated) {
                  final updatedAppreciations =
                      submission.appreciations
                          .where(
                            (interaction) =>
                                interaction.userId != currentUser.id,
                          )
                          .toList();
                  return submission.copyWithAppreciation(
                    appreciations: updatedAppreciations,
                    appreciationCount: updatedAppreciations.length,
                  );
                } else {
                  final newInteraction = UserInteraction(
                    interactionId:
                        'like_${DateTime.now().millisecondsSinceEpoch}',
                    userId: currentUser.id,
                    userName: currentUser.name,
                    userAvatar: currentUser.avatar,
                    interactedAt: DateTime.now(),
                  );
                  final updatedAppreciations = [
                    ...submission.appreciations,
                    newInteraction,
                  ];
                  return submission.copyWithAppreciation(
                    appreciations: updatedAppreciations,
                    appreciationCount: updatedAppreciations.length,
                  );
                }
              }
              return submission;
            }).toList();

        emit(state.copyWith(submissions: updatedSubmissions));
      }
    } catch (e) {
      Whisper.hiss('Failed to update appreciation: $e');
    }
  }

  Future<void> filterByCategory(SubmissionCategory? category) async {
    try {
      emit(state.copyWith(isProcessing: true, clearError: true));

      List<ContentSubmission> filteredSubmissions;
      if (category == null) {
        filteredSubmissions = await _repository.getAllSubmissions();
      } else {
        filteredSubmissions = await _repository.getSubmissionsByCategory(
          category,
        );
      }

      emit(
        state.copyWith(isProcessing: false, submissions: filteredSubmissions),
      );
    } catch (e) {
      emit(
        state.copyWith(
          isProcessing: false,
          errorMessage: 'Failed to filter content: $e',
        ),
      );
    }
  }

  Future<bool> deleteSubmission(String submissionId) async {
    try {
      emit(state.copyWith(isProcessing: true, clearError: true));

      final success = await _repository.removeSubmission(submissionId);

      if (success) {
        final updatedSubmissions =
            state.submissions
                .where((submission) => submission.submissionId != submissionId)
                .toList();

        emit(
          state.copyWith(isProcessing: false, submissions: updatedSubmissions),
        );

        return true;
      } else {
        throw Exception('Failed to delete content from storage');
      }
    } catch (e) {
      emit(
        state.copyWith(
          isProcessing: false,
          errorMessage: 'Failed to delete content: $e',
        ),
      );
      Whisper.hiss('Failed to delete content: $e');
      return false;
    }
  }

  void clearError() {
    emit(state.copyWith(clearError: true));
  }
}
